package com.ruoyi.common.utils;


import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 时间工具类--常用
 *
 * @author zhangjun
 */
public class NewDateUtils {

    private final static ThreadLocal<Map<String, SimpleDateFormat>> dfMap = new ThreadLocal<Map<String, SimpleDateFormat>>();

    private static String FORMAT_STRING_DATE = "yyyy-MM-dd HH:mm:ss SSS";

    public static final String FORMAT_STRING_DATELESS = "yyyy-MM-dd HH:mm:ss";

    public static String FORMAT_NORMAL = "yyyyMMddHHmmss";

    private static String YYYYMMDD = "yyyyMMdd";

    private static String YYYY_MM_DD = "yyyy.MM.dd";

    private static String YYYYMM_DD = "yyyy-MM-dd";

    private static String UTCFORMAT = "YYYY-MM-DDThh:mm:ssZ";

    public final static String YYYYMM = "yyyyMM";

    public final static String YYYY = "yyyy";

    /**
     * 确保每个线程有自己独立的DateFormat,避免并发影响，且用过的formatter都缓存起来，且用的是懒加载方式.避免创建一堆无用format
     *
     * @param key
     * @return
     */
    private static DateFormat getFormat(String key) {
        Map<String, SimpleDateFormat> map = dfMap.get();
        boolean empty = false;
        if (map == null) {
            map = new HashMap<String, SimpleDateFormat>();
            dfMap.set(map);
            empty = true;
        }
        SimpleDateFormat format = null;
        if (!empty) {
            format = map.get(key);
        }
        if (format == null) {
            if (FORMAT_STRING_DATE.equals(key)) {
                format = new SimpleDateFormat(key, Locale.US);
            } else {
                format = new SimpleDateFormat(key);
            }
            map.put(key, format);
        }
        return format;
    }

    /**
     * @return "yyyy-MM-dd HH:mm:ss SSS"
     */
    public static String formatDate(Date date) {
        return getFormat(FORMAT_STRING_DATE).format(date);
    }


    /**
     * @return "yyyy-MM-dd HH:mm:ss SSS"
     * @throws ParseException
     */
    public static Date formatDate(String date) throws ParseException {
        return getFormat(FORMAT_STRING_DATELESS).parse(date);
    }

    /**
     * 格式化日期格式
     *
     * @param date
     * @return
     */
    public static String format(Date date) {
        return format(date, FORMAT_STRING_DATELESS);
    }

    /**
     * 格式化日期格式
     *
     * @param date
     * @param format
     * @return
     */
    public static String format(Date date, String format) {
        if (date == null) {
            throw new IllegalArgumentException("date should not be null");
        }
        if (StringUtils.isBlank(format)) {
            throw new IllegalArgumentException("format should not be null");
        }
        return getFormat(format).format(date);
    }

    /**
     * @param date
     * @param format
     * @return
     */
    public static Date parse(String date, String format) {
        if (StringUtils.isBlank(date)) {
            throw new IllegalArgumentException("date should not be blank");
        }
        if (StringUtils.isBlank(format)) {
            throw new IllegalArgumentException("date should not be blank");
        }
        try {
            return getFormat(format).parse(date);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }

    public static Date parse(String date) {
        return parse(date);
    }


    /**
     * @return "yyyyMMddHHmmss"
     */
    public static String formatNormalDate(Date date) {
        return getFormat(FORMAT_NORMAL).format(date);
    }

    /**
     * @param date
     * @return YYYY-MM-DDThh:mm:ssZ
     */
    public static String formatUTCDate(Date date) {
        return getFormat(UTCFORMAT).format(date);
    }


    /**
     * @return "yyyy-MM-dd HH:mm:ss"
     */
    public static String formatDateStandard(Date date) {

        return getFormat(FORMAT_STRING_DATELESS).format(date);
    }

    /**
     * @param @param  d
     * @param @param  day
     * @param @return
     * @param @throws ParseException    设定文件
     * @return Date    返回类型
     * @throws
     * @Title: addDate
     * @Description: (输入日期 加天数，获取日期)
     * @author
     * @date
     */
    public static Date addDate(Date d, long day) throws ParseException {
        long time = d.getTime();
        day = day * 24 * 60 * 60 * 1000;
        time += day;
        return new Date(time);
    }

    /**
     * @param date
     * @param amount
     * @return
     */
    public static Date addDays(Date date, int amount) {
        return DateUtils.addDays(date, amount);
    }

    /**
     * @return "yyyy.MM.dd"
     */
    public static String formatDateToStringDay(Date date) {

        return getFormat(YYYY_MM_DD).format(date);
    }

    public static Date getYesterday() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, -1);
        return calendar.getTime();
    }

    public static Date beforeNDay(int n) {
        return beforeNDay(new Date(), n);
    }

    public static Date beforeNDay(Date date, int n) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DATE, -n);
        return calendar.getTime();
    }

    public static Date afterNDay(int n) {
        return afterNDay(new Date(), n);
    }

    public static Date afterNDay(Date date, int n) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DATE, n);
        return calendar.getTime();
    }

    /**
     * @return "yyyy-MM-dd"
     */
    public static String formatYYYYMMDD(Date date) {
        return getFormat(YYYYMM_DD).format(date);
    }

    /**
     * 日期的开始
     *
     * @param date
     * @return
     */
    public static String dateStart(Date date) {
        return getFormat(YYYYMM_DD).format(date) + " 00:00:00";
    }

    /**
     * 日期的结束
     *
     * @param date
     * @return
     */
    public static String dateEnd(Date date) {
        return getFormat(YYYYMM_DD).format(date) + " 23:59:59";
    }

    /**
     * 返回指定日期加上月数后的日期<br/>
     * 说明:某些特定日期数月后无此日期,则加月数后取最后一天,如（20140131加一个月后的日期为20130228）。
     *
     * @param date 指定日期
     * @param ms   所加月数
     * @return 加上月数后的日期
     */
    public static Date getNumMthDate(Date date, int ms) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, ms);
        return calendar.getTime();
    }

    /**
     * yyyy-MM-dd HH:mm:ss   转成Date
     * @param dateStr
     * @return
     */
    public static Date getDate(String dateStr) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            return format.parse(dateStr);
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 获取月份的第一天
     * @param date
     * @param formatStr
     * @return
     */
    public static Date getFirstDayOfMonth(String dateStr,String formatStr) {

        SimpleDateFormat format = new SimpleDateFormat(formatStr);
        try {
            Date date=format.parse(dateStr);
            Calendar cal=Calendar.getInstance();
            cal.setTime(date);
            cal.set(Calendar.DAY_OF_MONTH, 1);
            return cal.getTime();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    public static Date getFirstDayOfMonth(String dateStr) {
        return getFirstDayOfMonth(dateStr,YYYYMM);
    }

    /**
     * 得到当月起始时间
     *
     * @param date
     * @return
     */
    public static Date getMonthStart(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    /**
     * 得到month的终止时间点.
     *
     * @param date
     * @return
     */
    public static Date getMonthEnd(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        calendar.add(Calendar.MONTH, 1);
        calendar.add(Calendar.MILLISECOND, -1);
        return calendar.getTime();
    }
    /**
     * 获取月份的最后一天 如果是当月的话 取nowtime
     * @param date
     * @param formatStr
     * @return
     */
    public static Date getLastDayOfMonth(String dateStr,String formatStr) {
        SimpleDateFormat format = new SimpleDateFormat(formatStr);
        try {
            Date nowDate=new Date();
            String nowDateStr=format.format(nowDate);
            Date date=format.parse(dateStr);
            Date nowDateTmp=format.parse(nowDateStr);

            //当前月
            if(nowDateTmp.compareTo(date)==0) {
                return formatDate(dateEnd(nowDate));
            }
            Calendar cal=Calendar.getInstance();
            cal.setTime(date);
            cal.add(Calendar.MONTH, 1);
            cal.add(Calendar.MILLISECOND, -1);
            return cal.getTime();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    public static Date getLastDayOfMonth(String dateStr) {
        return getLastDayOfMonth(dateStr,YYYYMM);
    }

    /**
     * 获取指定时间所在月份
     * @param date
     */
    public static int getMonth(Date date){
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        //老外计算月份从0开始，转换为国内月份需要加1
        return cal.get(cal.MONTH) + 1;
    }

    /**
     * 获取指定时间所在季度
     * @param date
     */
    public static Integer getQuarter(Date date){
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        //老外计算月份从0开始，转换为国内月份需要加1
        int month = cal.get(cal.MONTH) + 1;
        if (month>=1 && month <= 3) {
            return 1;
        }
        if (month>=4 && month <= 6) {
            return 2;
        }
        if (month>=7 && month <= 9) {
            return 3;
        }
        if (month>=10 && month <= 12) {
            return 4;
        }

        return null;
    }

    public static int getWeek(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setFirstDayOfWeek(Calendar.MONDAY);
        calendar.setTime(date);
        return calendar.get(Calendar.WEEK_OF_YEAR);
    }


}
